package com.tvserials.notification.sync;

import android.accounts.Account;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.*;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.tvserials.notification.MainAppActivity;
import com.tvserials.notification.R;
import com.tvserials.notification.dto.Episode;
import com.tvserials.notification.dto.Serial;
import com.tvserials.notification.exceptions.NetworkConnectionException;
import com.tvserials.notification.exceptions.PageParseException;
import com.tvserials.notification.preferences.SharedPreferencesUtils;
import com.tvserials.notification.services.NotificationService;
import com.tvserials.notification.services.ServiceFactory;
import com.tvserials.notification.utils.NetworkUtils;
import com.tvserials.notification.utils.ResourceUtils;
import com.tvserials.notification.utils.VOUtils;
import com.tvserials.notification.vo.SourceType;
import com.tvserials.notification.vo.TvEpisodeFilterVO;

import java.util.*;

/**
 * Created by Alex on 04.05.2014.
 */
public class EpisodeSyncAdapter extends AbstractThreadedSyncAdapter {
    private static final String TAG = "SynchronizeService";
    private NotificationManager nm;
    private static boolean isRunning = false;

    private final ContentResolver mContentResolver;
    private Context context;

    public EpisodeSyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        this.context = context;
        mContentResolver = context.getContentResolver();
    }

    public EpisodeSyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {
        super(context, autoInitialize, allowParallelSyncs);
        this.context = context;
        mContentResolver = context.getContentResolver();
    }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
        Log.w(TAG, "Perform sync for account ..." + account.name);
        boolean useOnlyWifi = SharedPreferencesUtils.getUseOnlyWifi(context);
        if (!isRunning) {
            if (NetworkUtils.isConnected(context) && (!useOnlyWifi || (NetworkUtils.isConnectedWifi(context)))) {
                Date currentTime = new Date();
                Date startTime = SharedPreferencesUtils.getStartTime(context);
                Date endTime = SharedPreferencesUtils.getEndTime(context);
                boolean dontDisturbTime = currentTime.after(startTime) && currentTime.before(endTime);
                if (!dontDisturbTime) {
                    isRunning = true;
                    new SendNotificationTask(context).execute();
                }
            } else {
                Log.w(TAG, "There is no available network connection");
            }
        } else {
            Log.w(TAG, "Service is currently running");
        }
    }

    private class SendNotificationTask extends AsyncTask<Void, Void, List<Episode>> {
        private Context context;

        private SendNotificationTask(Context context) {
            this.context = context;
        }

        @Override
        protected List<Episode> doInBackground(Void... voids) {
            Log.w(TAG, "Synchronizing episodes ...");
            List<Serial> selectedSerials = SharedPreferencesUtils.getSerialsList(context);
            Date syncDate = SharedPreferencesUtils.getSyncDate(context);

            TvEpisodeFilterVO filterVO = new TvEpisodeFilterVO(1, syncDate, selectedSerials);
            filterVO.setSourceTypes(SharedPreferencesUtils.getSelectedSourceTypes(context));
            List<Episode> tvChapterVOs = getEpisodes(filterVO);

            return tvChapterVOs;
        }

        public List<Episode> getEpisodes(TvEpisodeFilterVO filterVO) {
            try {
                NotificationService pageParser = ServiceFactory.getNotificationService();
                List<Episode> tvChapterVOs = pageParser.getEpisodes(filterVO);
                return tvChapterVOs;
            } catch (NetworkConnectionException e) {
                Log.w(TAG, "Failed to read data", e);
            } catch (PageParseException e) {
                Log.w(TAG, "Failed to parse data", e);
            }
            return new ArrayList<Episode>();
        }

        @Override
        protected void onPostExecute(List<Episode> tvChapterVOs) {
            super.onPostExecute(tvChapterVOs);
            isRunning = false;
            nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            if (VOUtils.isListNotEmpty(tvChapterVOs)) {
                if (tvChapterVOs.size() > 8) {
                    sendNotificationsBySourceType(tvChapterVOs);
                } else {
                    sendNotificationsBySerials(tvChapterVOs);
                }
                saveEpisodesToCache(tvChapterVOs);
                //update sync time to last shown item
                SharedPreferencesUtils.updateSyncDate(context, tvChapterVOs.get(0).getReleaseDate());
            }

            nm = null;
        }

        private void saveEpisodesToCache(List<Episode> tvChapterVOs) {
            List<Episode> cachedEpisodes = SharedPreferencesUtils.getEpisodes(context);
            if (VOUtils.isListNotEmpty(cachedEpisodes)) {
                tvChapterVOs.addAll(cachedEpisodes);
            }
            int history = SharedPreferencesUtils.getHistoryNo(context);
            SharedPreferencesUtils.saveEpisodes(context, VOUtils.strictList(tvChapterVOs, history));
        }


        private void sendNotificationsBySerials(List<Episode> tvEpisodes) {
            Map<Serial, List<Episode>> serials = VOUtils.groupBySerials(tvEpisodes);
            int i = 1;
            for (Serial serial : serials.keySet()) {
                List<Episode> episodes = VOUtils.sortByDate(serials.get(serial));
                if (!episodes.isEmpty()) {
                    sendNotification(episodes, i == serials.size());
                }
                i++;
            }
        }

        private void sendNotificationsBySourceType(List<Episode> tvChapterVOs) {
            Map<SourceType, List<Episode>> episodesMap = VOUtils.groupBySourceType(tvChapterVOs);
            for (SourceType sourceType : episodesMap.keySet()) {
                List<Episode> episodes = episodesMap.get(sourceType);

                String episodesLabel = context.getResources().getString(R.string.new_episodes);
                String summaryText = String.format("%d %s", episodes.size(), episodesLabel);

                String contentTitle = context.getResources().getStringArray(R.array.navigationTitles)[sourceType.ordinal()];

                NotificationCompat.Builder mBuilder =
                        new NotificationCompat.Builder(context)
                                .setSmallIcon(ResourceUtils.getIconResourceId(sourceType))
                                .setContentTitle(contentTitle)
                                .setContentText(summaryText)
                                .setWhen(episodes.get(0).getReleaseDate().getTime())
                                .setAutoCancel(true)
                                .setOnlyAlertOnce(true);

                addNotificationEffects(true, mBuilder);
                addInboxStyle(episodes, mBuilder);
                addNotificationPendingIntent(sourceType, mBuilder);

                Notification notification = mBuilder.build();
                nm.notify(new Random().nextInt(), notification);
            }
        }

        private void sendNotification(List<Episode> episodes, boolean addSound) {
            Episode tvChapterVO = episodes.get(0);

            Log.w(TAG, tvChapterVO.toString());
            String chapterNumber = tvChapterVO.getChapterNumber();
            String contentText = tvChapterVO.getChapterName();
            if (chapterNumber != null) {
                contentText = String.format("%s (%s)", tvChapterVO.getChapterName(), chapterNumber);
            }

            Bitmap icon = null;
            if (tvChapterVO.getImage() != null) {
                icon = BitmapFactory.decodeByteArray(tvChapterVO.getImage(), 0, tvChapterVO.getImage().length);
            }

            NotificationCompat.Builder mBuilder =
                    new NotificationCompat.Builder(context)
                            .setSmallIcon(ResourceUtils.getIconResourceId(tvChapterVO.getSourceType()))
                            .setContentTitle(tvChapterVO.getShowName())
                            .setContentText(contentText)
                            .setWhen(tvChapterVO.getReleaseDate().getTime())
                            .setLargeIcon(icon)
                            .setAutoCancel(true)
                            .setOnlyAlertOnce(true);

            if (episodes.size() > 1) {
                addInboxStyle(episodes, mBuilder);
            }

            addNotificationEffects(addSound, mBuilder);

            addNotificationPendingIntent(tvChapterVO.getSourceType(), mBuilder);

            Notification notification = mBuilder.build();
            nm.notify(VOUtils.getUniqueID(tvChapterVO), notification);
        }

        private void addNotificationPendingIntent(SourceType sourceType, NotificationCompat.Builder mBuilder) {
            Intent browserIntent = new Intent(context, MainAppActivity.class);
            browserIntent.putExtra(MainAppActivity.NAV_POSITIION_EXTRA, sourceType.ordinal());

            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, browserIntent, 0);
            mBuilder.setContentIntent(pendingIntent);
        }

        private void addNotificationEffects(boolean addSound, NotificationCompat.Builder mBuilder) {
            if (addSound) {
                Uri ringtoneUri = SharedPreferencesUtils.getRingtoneUri(context);
                mBuilder.setSound(ringtoneUri);
            }

            if (SharedPreferencesUtils.getIndicator(context)) {
                mBuilder.setLights(Color.CYAN, 300, 4000);
            }

            if (SharedPreferencesUtils.getVibration(context)) {
                mBuilder.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
            }
        }

        private void addInboxStyle(List<Episode> episodes, NotificationCompat.Builder mBuilder) {
            NotificationCompat.InboxStyle inboxStyle = new
                    NotificationCompat.InboxStyle();
//            inboxStyle.setBigContentTitle();
            for (Episode line : episodes) {
                inboxStyle.addLine(String.format("%s - %s",line.getShowName(),line.getChapterName()));
            }
            String newEpisodesLabel = context.getResources().getString(R.string.new_episodes);
            String summaryText = String.format("%d %s", episodes.size(), newEpisodesLabel);
            inboxStyle.setSummaryText(summaryText);
            mBuilder.setContentText(summaryText);
            mBuilder.setStyle(inboxStyle);
        }
    }

}
